package com.shengqin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shengqin.common.pojo.CommonPage;
import com.shengqin.config.CommonException;
import com.shengqin.entity.Menu;
import com.shengqin.entity.Role;
import com.shengqin.entity.RoleMenu;
import com.shengqin.mapper.RoleMapper;
import com.shengqin.pojo.user.RoleSaveParam;
import com.shengqin.service.IMenuService;
import com.shengqin.service.IRoleMenuService;
import com.shengqin.service.IRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Resource
    private IRoleMenuService roleMenuService;
    @Resource
    private IMenuService menuService;

    @Override
    public Page<Role> queryPage(CommonPage<Role> queryPageParam) {
        Role queryParam = queryPageParam.getQueryParam();
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        if (StringUtils.hasLength(queryParam.getName())) {
            wrapper.lambda().like(Role::getName, queryParam.getName());
        }
        if (StringUtils.hasLength(queryParam.getCode())) {
            wrapper.lambda().like(Role::getCode, queryParam.getCode());
        }
        Object loginId = StpUtil.getLoginId();
        if (loginId == null) {
            return new Page<>();
        }
        if (!loginId.equals("1")) {
            wrapper.lambda().eq(Role::getCreateUserId, loginId.toString());
        }
        Page<Role> page = new Page<>(queryPageParam.getPageNo(), queryPageParam.getPageSize());
        page(page, wrapper);
        buildRecords(page.getRecords());
        return page;
    }

    private void buildRecords(List<Role> records) {
        if (!CollectionUtils.isEmpty(records)) {
            List<Menu> menuList = menuService.list();
//            Map<Integer, Menu> menuMap = menuList.stream().collect(Collectors.toMap(Menu::getId, m -> m));
            Set<Integer> roleIds = new HashSet<>();
            records.forEach(item -> {
                records.forEach(role -> {
                    roleIds.add(role.getId());
                });
            });

            List<RoleMenu> roleMenuList = roleMenuService.listByRoleIds(roleIds);
            Map<Integer, List<RoleMenu>> roleMenuMap = roleMenuList.stream().collect(Collectors.groupingBy(RoleMenu::getRoleId));
            records.forEach(item -> {
                List<RoleMenu> roleMenus = roleMenuMap.get(item.getId());
                if (!CollectionUtils.isEmpty(roleMenus)) {
                    item.setCheckedKeys(roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList()));
                }
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean onSave(RoleSaveParam roleSaveParam) {
        if (CollectionUtils.isEmpty(roleSaveParam.getSelectKeys())) {
            throw new CommonException("请先选择权限");
        }
        Role role = new Role();
        BeanUtils.copyProperties(roleSaveParam, role);
        if (roleSaveParam.getId() == null) {
            Role roleCode = getByCode(role.getCode());
            if (roleCode != null) {
                throw new CommonException("角色编码已存在，请重新输入");
            }
            role.setCreateTime(LocalDateTime.now());
            role.setCreateUserId(Integer.valueOf(StpUtil.getLoginId().toString()));
        }
        saveOrUpdate(role);

        roleMenuService.removeByRoleId(role.getId());

        List<RoleMenu> roleMenuList = new ArrayList<>();
        roleSaveParam.getSelectKeys().forEach(key -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(role.getId());
            roleMenu.setMenuId(Integer.parseInt(key));
            roleMenuList.add(roleMenu);
        });
        return roleMenuService.saveBatch(roleMenuList);
    }

    private Role getByCode(String code) {
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Role::getCode, code);
        return getOne(wrapper);
    }
}
